home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-03
/
pb3brows.zip
/
ABROWSE.BAS
next >
Wrap
BASIC Source File
|
1993-04-02
|
14KB
|
460 lines
'******************************************************************************
'* PowerBasic 3 assembler module for viewing files *
'* Use with module BROWSE.BAS *
'* (c) Hans Lunsing - 04/1993 *
'******************************************************************************
$DIM ARRAY
$ERROR ALL -
$LIB LPT -, COM -, GRAPH -, FULLFLOAT -, IPRINT -
$OPTIMIZE SIZE
$OPTION CNTLBREAK -, GOSUB +
$STRING 1
DEFWRD A-Z ' <========================================= IMPORTANT!!!!!
$INCLUDE "GENERAL.BI"
SHARED Handle% ' [BX+00] Filehandle
SHARED FilePtr& ' [BX+02] Filepointer, Low byte
' [BX+04] Filepointer, High byte
SHARED CacheSize ' [BX+06] Cache size in WORDS
SHARED CacheSeg ' [BX+08] Cache Segment
SHARED LowCache ' [BX+10] offset Low cache part
SHARED HighCache ' [BX+12] offset High cache part
SHARED EndCache ' [BX+14] offset end of active cache
SHARED CachePtr ' [BX+16] cachepointer
SUB ShowFile (BYVAL FirstRow%, BYVAL TextRows%, BYVAL BeginColumn%, _
BYVAL TextAttr%, BYVAL Filter%) PUBLIC
LOCAL BeginOffset, EndColumn%, GlobalOfs, VideoOffs%, VideoSeg%
IF Handle% < 0 THEN EXIT SUB
CALL GetVideoAddress (VideoSeg%, VideoOffs%)
GlobalOfs = VARPTR(Handle%)
EndColumn% = BeginColumn% + pbvScrnCols
BeginOffset = CWRD(FirstRow% - 1) * pbvScrnCols * 2
!MOV BX, GlobalOfs
!MOV ES, VideoSeg% 'Put segment video page in ES
!MOV SI, [BX+16] 'Put cachepointer in SI
!XOR DL,DL 'Make linecounter 0
!MOV DH,BYTE PTR TextRows% 'Max number of lines in DH
SFNextLine:
!CALL NEAR PTR OffsLine
!XOR BX,BX 'Make positioncounter 0
SFNextByte:
!PUSH BX
!MOV BX, GlobalOfs
!CALL NEAR PTR GetNextByte 'Load next byte in AL
!POP BX
!JC SFFinish 'Ready if carryflag
!AND AL,BYTE PTR Filter% 'Wordstar filter
!CMP AL,%CR 'Is it CR ?
!JZ SFNextByte 'Yes, get next byte
!CMP AL,%LF 'Is it LF ?
!JZ SFEndLine 'Yes, process line
!CMP AL,%TAB 'Is it TAB ?
!JZ SFTAB 'Yes, process TAB
!MOV CX, 1 'Normal character:
'repeatcounter to 1
SFNormChar:
!CMP BX,BeginColumn% 'Compare positioncounter to start column
!JC SFEndByte 'If smaller: skip
!CMP BX,EndColumn% 'Compare positioncounter to end column
!JNC SFEndByte 'If >= : skip
!MOV AH,BYTE PTR TextAttr% 'Put attribute in AH
!CMP pbvScrnCard, %CGA 'CGA ? (all bits of pbvScrnCard except bit 1 are 0)
!JZ SFCGA 'yes, process separately
!STOSW 'put character and attrib on the scherm
!JMP SFEndByte
'CGA: wait for horizontal retrace (sync)
SFCGA:
!PUSH AX
!PUSH DX
!MOV DX, &H3DA
!CLI 'disable interrupts
SFL1:
!IN AL,DX ' Read video status
!TEST AL,1 ' horizontal retrace active ?
!JNZ SFL1 ' yes, wait until done
SFL2:
!IN AL,DX ' No, Read status
!TEST AL,1 ' and wait for retrace
!JZ SFL2
!POP DX
!POP AX
!STOSW
!STI 'enable interrupts
SFEndByte:
!INC BX 'increment positioncounter
!LOOP SFNormChar 'repeat until CX = 0
!JMP SFNextByte 'get next byte
SFTAB:
!MOV AX,BX 'positioncounter in AX
!AND AX,7 'position modulo 8
!MOV CX,8 '8 in CX
!SUB CX,AX 'subtract position mod 8
!MOV AL,32 'load space in AL
!JMP SFNormChar 'Repeat CX times on the screen
SFEndLine:
!CALL NEAR PTR FillLine
!INC DX 'increment line counter (INC DL doesnot work in pb3)
!CMP DL,DH 'equals screen lines ?
!JC SFNextLine 'No, get next line
SFFinish:
!CMP AL,%LF 'last read character LF ?
!JZ SFL0 'No, fill with spaces
!CALL NEAR PTR FillLine
!INC DX 'And increment linecounter(INC DL but not in pb3)
SFL0:
!CMP DL, DH 'all screenlines occupied ?
!JNC SFExit 'yes, ready!
!CALL NEAR PTR OffsLine 'Calculate offset new line
!MOV AL, DH 'calculate remaining positions
!SUB AL, DL 'on the screen in CX
!MUL pbvScrnCols
!MOV CX, AX
!CALL NEAR PTR PlaceSpaces 'Clear the rest of the screen
SFExit:
EXIT SUB
OffsLine:
!MOV AL,BYTE PTR pbvScrnCols 'Put Number of videocolumns in AL,
!MUL DL 'Multiply by number of lines
'uptil now
!SHL AX,1 'multiply by 2 (byte -> woord)
!MOV DI,AX 'result in DI
!ADD DI,VideoOffs% 'add video page plus first line
!ADD DI,BeginOffset 'to get offset to the next line.
!RETN
FillLine:
!CMP BX,EndColumn% 'Compare postioncounter to end column
!JNC FLExit 'If =>: ready
!CMP BX,BeginColumn% 'compare positioncounter to start column
!JNC FLL0 'If =>: continue
!MOV BX, BeginColumn%
FLL0:
!MOV CX, EndColumn%
!SUB CX, BX 'CX = number of positions to clear
!PUSH AX
!CALL NEAR PTR PlaceSpaces 'Clear the rest of the line
!POP AX
FLExit:
!RETN
PlaceSpaces:
!MOV AL,32 'AX = space + attribute
!MOV AH,BYTE PTR TextAttr%
!REP STOSW 'Clear rest of the screen
!RETN
END SUB
SUB InitBrowseFile (BYVAL FHandle, BYVAL CSeg, BYVAL COffs, BYVAL CSize) PUBLIC
Handle% = FHandle
CacheSeg = CSeg
LowCache = COffs
CacheSize = CSize
HighCache = LowCache + CacheSize
CALL HomeFile
END SUB
SUB ExitBrowseFile PUBLIC
Handle% = -1
END SUB
SUB LineDown PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
!MOV BX, GlobalOfs
!PUSH SI
!MOV SI, [BX+16] 'cachepointer in SI
!CALL NEAR PTR ScanDown
!MOV [BX+16], SI 'update cachepointer
!POP SI
END SUB
SUB LineUp PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
!MOV BX, GlobalOfs
!PUSH SI
!MOV SI, [BX+16] 'cachepointer in SI
!CALL NEAR PTR ScanUp
!MOV [BX+16], SI 'update cachepointer
!POP SI
END SUB
SUB PageDown (BYVAL TextRows%) PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
!MOV BX, GlobalOfs
!PUSH SI
!MOV SI, [BX+16] 'cachepointer in SI
!MOV CX, TextRows%
PDL0:
!CALL NEAR PTR ScanDown 'as many lines Down as
!LOOP PDL0 'textlines on the screen
!MOV [BX+16], SI 'update cachepointer
!POP SI
END SUB
SUB PageUp (BYVAL TextRows%) PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
!MOV BX, GlobalOfs
!PUSH SI
!MOV SI, [BX+16] 'cachepointer in SI
!MOV CX, TextRows%
PUL0:
!CALL NEAR PTR ScanUp 'as many lines Up as
!LOOP PUL0 'textlines on the screen
!MOV [BX+16], SI 'update cachepointer
!POP SI
END SUB
SUB HomeFile PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
FilePtr& = 0
CachePtr = LowCache
!MOV BX, GlobalOfs
!MOV DX, [BX+10] 'startaddress low cache in DX
!MOV CX, [BX+06] 'cachesize in CX
!SHL CX,1 'multiply 2 is number of bytes read
!CALL NEAR PTR FileToCache 'Read bytes from file in cache
END SUB
SUB EndFile(BYVAL TextRows%) PUBLIC
LOCAL GlobalOfs
IF Handle% < 1 THEN EXIT SUB
GlobalOfs = VARPTR(Handle%)
!MOV BX, GlobalOfs
!PUSH SI
!MOV SI, [BX+16] 'cachepointer in SI
EFL0:
!PUSH SI 'Save cachepointer
!CALL NEAR PTR ScanDown 'nextline
!POP AX 'Restore old pointer
!CMP AX,SI 'compare old and new pointer
!JNZ EFL0 'continue if equal
!MOV CX, TextRows% 'Put pointer to start of nextscreen
EFL1:
!CALL NEAR PTR ScanUp 'pageup
!LOOP EFL1
!MOV [BX+16], SI 'update cachepointer
!POP SI
END SUB
'-----------------------------------------------------------------------------
GetNextByte:
!CMP SI,[BX+14] 'is cachepointer end of active cache or >
!JC GNBL0
!JMP GNBExit 'yes, return with carry (ready)
'Direct short jump to GNBExit is not possible
'because of the basicstatements in between
GNBL0:
!MOV AX, [BX+06]
!SHL AX, 1 'cachepointer to end of highcache or up?
!CMP SI, AX
!JNC GNBL1
!JMP GNBLoadNext 'No, load byte in AL
'and return without carry
'yes, move contents highcache to lowcache
'read part of file in highcache:
'Save registers CX, DX, DI and ES
GNBL1:
!PUSH CX 'loopcounter PgUp/PgDn
!PUSH DX 'linecounter
!PUSH DI 'screenoffset
!PUSH ES 'screensegment
'Contents high cache to low:
!MOV SI, [BX+12] 'Let SI be source
!MOV DI, [BX+10] 'and DI be destination
!MOV CX, [BX+06] 'Put (half the) CacheSize in CX
!PUSH DS
!MOV ES, [BX+08] 'ES and DS point to
!PUSH ES 'cachesegment
!POP DS
!REPZ MOVSB 'move contents of the cache
!POP DS
'Fill high cache from file:
FilePtr& = FilePtr& + 2 * CacheSize ' filepointer
!MOV SI, DI 'SI points to end of low cache
!MOV CX, [BX+06] 'Zet CacheSize in CX
!MOV DX, [BX+12] 'DX points to high cache
!CALL NEAR PTR FileToCache 'read CacheSize bytes from file into high cache
CachePtr = CachePtr - CacheSize 'Update cachepointer
FilePtr& = FilePtr& - CacheSize 'update filepointer for next read
!POP ES 'Restore registers
!POP DI
!POP DX
!POP CX
!JMP GetNextByte 'load first byte
GNBLoadNext:
!PUSH DS
!MOV DS, [BX+08]
!LODSB 'Load byte in AL and update SI
!POP DS
GNBExit:
!CMC 'Complement carry flag.
!RETN
'-----------------------------------------------------------------------------
GetPreviousByte:
!CMP SI, [BX+10] 'cachepointer past start
'lage cache ?
!JBE GPBL0
!JMP GPBLoadPrev 'Yes, load previous byte and return
GPBL0:
!MOV AX, [BX+02] 'No:,
!OR AX, [BX+04] ' Filepointer zero ?
!JNZ GPBL1
!JMP GPBExitC 'Yes, begin file found,
'return with carry
'No, move lowcache to high
'and fill low cache from file:
'save registers CX, DX, DI and ES
GPBL1:
!PUSH CX 'loopcounter PgUp/PgDn
!PUSH DX 'linecounter
!PUSH DI 'screenoffset
!PUSH ES 'screensegment
'contents low cache to high:
!MOV SI, [BX+10] 'SI points to source
!MOV DI, [BX+12] 'DI to destination
!MOV CX, [BX+06] '(half) CacheSize in CX
!PUSH DS
!MOV ES, [BX+08] 'ES and DS point to
!PUSH ES 'cachesegment
!POP DS
!REPZ MOVSB 'Move contents cache
!POP DS
'Fill Low cache from file:
FilePtr& = FilePtr& - CacheSize 'file pointer
!MOV CX, [BX+06] 'CacheSize in CX
!MOV DX, [BX+10] 'DX to low cache
!CALL NEAR PTR FileToCache 'Read CacheSize bytes from file to low cache
CachePtr = CachePtr + CacheSize 'Update cachepointer
!POP ES 'restore registers
!POP DI
!POP DX
!POP CX
GPBLoadPrev:
!PUSH DS
!MOV DS, [BX+08]
!DEC SI 'update SI
!MOV AL, BYTE PTR [SI] 'Load byte in AL
!POP DS
!XOR AH, AH
!RCR AH, 1 'clear carry.CLC instruction does not work PB
!JMP GPBExit
GPBExitC:
!STC 'set carry
GPBExit:
!RETN
'-----------------------------------------------------------------------------
FileToCache:
!PUSH BP
!MOV BP, SP ' stackframe
' save registers:
!PUSH DS ' [BP-02] default datasegment
!PUSH BX ' [BP-04] BX contains pointer to global shared vars
!PUSH CX ' CX contains number of bytes to read,
!PUSH DX ' DX contains offset to CacheSeg
EndCache = 65535 ' end of Cache op FFFFh. assignment of
' &HFFFF does not work properly.
!MOV DX, [BX+02] ' put required position
!MOV CX, [BX+04] ' filepointer in CX:DX
!MOV AL,0 ' LSEEK with AL=0 -> byte offset
' from start of file asked.
!MOV AH, &H42
!MOV BX, [BX] ' filehandle in BX
!INT &H21 ' move filepointer
' new position in DX:AX (=CX:DX)
!MOV BX, [BP-04] ' restore BX
!MOV CX, [BX] ' handle temporary in CX
!MOV DS, [BX+08] ' segment cache in DS
!MOV BX, CX ' handle now in BX
!POP DX ' restore DX and CX to read the file
!POP CX
!MOV AH, &H3F
!INT &H21 ' read bytes from file in cache
!POP BX ' restore BX and DS
!POP DS
!JNC FTCL0 ' attempt ok: continue
!XOR AX,AX ' if not, zero bytes read
FTCL0:
!CMP AX,CX ' Number of bytes read equal to
' length half the cache ?
!JZ FTCL1 ' Yes, file not completely read
!ADD AX,DX ' No, calculate the end of the relevant cache
' as offset cache scope plus number of bytes read
!MOV [BX+14],AX ' and save.
FTCL1:
!POP BP
!RETN
'-----------------------------------------------------------------------------
ScanDown:
!CALL NEAR PTR GetNextByte 'Read next byte
!JC SDExit 'return if EOF
!CMP AL,%LF 'LineFeed ?
!JNZ ScanDown 'No,Next byte
SDExit:
!RETN
'-----------------------------------------------------------------------------
ScanUp:
!CALL NEAR PTR GetPreviousByte
!JC SUExit 'return if begin file
SULoop:
!CALL NEAR PTR GetPreviousByte
!JC SUExit 'return if begin file
!CMP AL,%LF 'LineFeed ?
!JNZ SULoop 'No, farther back again
!CALL NEAR PTR GetNextByte 'yes, load byte after LF back
SUExit:
!RETN